package com.turing.pre.processor.file.processor;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.turing.common.util.FdfsUtils;
import com.turing.common.util.FileUtils;
import com.turing.common.util.StringUtils;
import com.turing.pre.processor.domain.FileImage;
import com.turing.pre.processor.service.FileImageService;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.ParseException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.pdfbox.text.TextPosition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import technology.tabula.CommandLineApp;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;

@Component
public class PDFProcessor {

    @Value( "${fdfs.domain}" )
    private String FDFS_FILE_DOMAIN;

    @Autowired
    private FileImageService fileImageService;

    private static Logger logger = LoggerFactory.getLogger(PDFProcessor.class);



    public boolean pdf2png(String taskSn, int preTaskDetailId, String pdfPath, String filename, String type, String desPath, int belongsElec) throws IOException {

        // 将pdf装图片 并且自定义图片得格式大小
        boolean success = false;
        File file = new File(pdfPath);
        try (PDDocument doc = PDDocument.load(file)) {
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();

            File desDir = new File(desPath);
            if (!desDir.exists()) {
                desDir.mkdirs();
            }
            for (int i = 0; i < pageCount; i++) {
                logger.info(">>>>>>> rendering pdf image ..... page " + i);
                //BufferedImage image = renderer.renderImageWithDPI(i, 144); // Windows native DPI
//                BufferedImage image = renderer.renderImage(i); // Windows native DPI
                BufferedImage image;
                // 电子版文件不做图片放大处理，图片只用作前端展示
                if (belongsElec == 1) {
                    image = renderer.renderImage(i);
                } else {
                    image = renderer.renderImage(i,2.0f); // 调整转换后的图片大小，用于提高精度
                }
                File imageFile = new File(desPath + "/" + filename + "_" + (i) + "." + type);
                boolean wrote = ImageIO.write(image, type, imageFile);
                String url = FdfsUtils.uploadFile(imageFile);
                success = wrote && !StringUtils.isEmpty(url);
                if (success) {
                    fileImageService.save(FileImage.builder().taskSn(taskSn)
                            .preTaskDetailId(preTaskDetailId)
                            .imageUrl(url)
                            .width(image.getWidth())
                            .height(image.getHeight())
                            .pageNo(i).build());
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return success;

    }

    public static void main(String[] args) {

        getPdfLocationByPage("D:\\富国_基金分红单1.pdf","D:\\tmp\\1.json");

    }

    public static void getPdfLocationByPage(String pdfpath, String locationPath) {
        String[] args = new String[]{"-f=JSON", "-p=all", "-n", pdfpath};

        try {
            CommandLineParser parser = new DefaultParser();
            CommandLine cmd = parser.parse(CommandLineApp.buildOptions(), args);
            StringBuilder stringBuilder = new StringBuilder();
            new CommandLineApp(stringBuilder, cmd).extractTables(cmd);
            FileUtils.StringToFile(stringBuilder.toString(), locationPath);
        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    public static void getPdfLocationByTable(String pdfpath, String locationPath) {
        String[] args = new String[]{"-f=JSON", "-p=all", pdfpath, "-r", "-u"};

        try {
            CommandLineParser parser = new DefaultParser();
            CommandLine cmd = parser.parse(CommandLineApp.buildOptions(), args);
            StringBuilder stringBuilder = new StringBuilder();
            new CommandLineApp(stringBuilder, cmd).extractTables(cmd);
            JSONArray jArr = JSONArray.parseArray(stringBuilder.toString());
            JSONArray newArr = new JSONArray();
            for (int i = 0; i < jArr.size(); i++) {
                JSONObject jObj = jArr.getJSONObject(i);
                Long height = jObj.getLong("height");
                if (height > 100) {
                    newArr.add(jObj);
                }
            }
//            FileUtils.StringToFile( stringBuilder.toString(), locationPath );
            FileUtils.StringToFile(newArr.toString(), locationPath);
//            FileUtils.StringToFile(stringBuilder.toString(),locationPath);

        } catch (ParseException e) {
            e.printStackTrace();
        }
    }
    //pdf分页

    /**
     * 将PDF文件切分成多个PDF
     *
     * @param filePath  文件名
     * @param splitSize 拆分单个文件页数
     */
    public static void splitPdf(String filePath, int splitSize, String pathPackage, String name) throws IOException, DocumentException {

        PdfReader reader = new PdfReader(filePath);

        int numberOfPages = reader.getNumberOfPages();
        int newFileCount = 0;
        // PageNumber是从1开始计数的
        int pageNumber = 1;
        while (pageNumber <= numberOfPages) {
            Document doc = new Document();
            String splitFileName = pathPackage + name + "_" + newFileCount + ".pdf";
            File file = new File(splitFileName);
            if (!file.exists()) {
                file.createNewFile();
            }
            PdfCopy pdfCopy = new PdfCopy(doc, new FileOutputStream(splitFileName));

            doc.open();
            // 将pdf按页复制到新建的PDF中
            for (int i = 1; pageNumber <= numberOfPages && i <= splitSize; ++i, pageNumber++) {
                doc.newPage();
                PdfImportedPage page = pdfCopy.getImportedPage(reader, pageNumber);
                pdfCopy.addPage(page);
            }
            doc.close();
            newFileCount++;
            pdfCopy.close();
        }

    }

    public static final String PNG_SUFFIX = ".jpg";

    public static void pdf2png(File file, String targetPath) {
        // 将pdf装图片 并且自定义图片得格式大小
        PDDocument doc = null;
        try {
            doc = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            for (int i = 0; i < pageCount; i++) {
                BufferedImage image = renderer.renderImageWithDPI(i, 72); // Windows native DPI
                File imageFile = new File(targetPath + "{" + i + "}" + PNG_SUFFIX);
                if (!imageFile.exists()) {
                    imageFile.mkdirs();
                }
                ImageIO.write(image, "jpg", imageFile);
                image.flush();

            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                doc.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }

    public static JSONArray getTextFromPdf(String path) throws IOException {

        JSONArray jsonResult = new JSONArray();

        PDDocument document = PDDocument.load(new File(path));

        int pages = document.getNumberOfPages();
        PDFTextStripper2 stripper2 = new PDFTextStripper2();

        for (int i = 1; i <= pages; i++) {
            stripper2.setStartPage(i);
            stripper2.setEndPage(i);
            stripper2.getText(document);//读取当前页的全部内容

            List<List<TextPosition>> ll = stripper2.getCharactersByArticle();
            List<TextPosition> ls = ll.get(0);//读取PDF

            JSONArray jsonArray = new JSONArray();
            for (TextPosition tp : ls) {
                JSONObject jsonObject = new JSONObject();
                String c = tp.getUnicode();
                float Y = tp.getY();
                float endY = tp.getEndY();
                float height = tp.getHeight();
                float width = tp.getWidth();
                float endX = tp.getEndX();
                jsonObject.put("y", (endY - height / 3));
                jsonObject.put("x", (endX - width));
                jsonObject.put("height", (height * 2));
                jsonObject.put("width", width);
                jsonObject.put("text", c);
                jsonObject.put("pageNum", i);
                jsonArray.add(jsonObject);
            }

            jsonResult.add(jsonArray);
        }
        return jsonResult;
    }

    public static void extractedNoTables(int i, JSONArray lines, JSONArray data) {
        //不包含表格
        for (int i2 = 0; i2 < data.size(); i2++) {
            JSONObject line = new JSONObject();
            JSONArray jsonObjectLines = data.getJSONArray(i2);
            JSONArray jsonObjectLinesNew = new JSONArray();
            Double topLine = null;
            Double leftLine = null;
            Double widthLine = null;
            Double heightLine = null;
            String textLine = "";

            for (int i1 = 0; i1 < jsonObjectLines.size(); i1++) {
                JSONObject jsonObjectLine1 = jsonObjectLines.getJSONObject(i1);
                Double topLineL = jsonObjectLine1.getDouble("top");
                Double leftLineL = jsonObjectLine1.getDouble("left");
                Double widthLineL = jsonObjectLine1.getDouble("width");
                Double heightLineL = jsonObjectLine1.getDouble("height");
                String textLineL = jsonObjectLine1.getString("text");

                if (!topLineL.equals(0) && !leftLineL.equals(0) && !widthLineL.equals(0) && !heightLineL.equals(0)) {
                    if (!textLineL.equals("")) {
                        jsonObjectLinesNew.add(jsonObjectLine1);
                        textLine += textLineL;
                    }
                }
            }

            if (jsonObjectLinesNew.size() > 1) {
                JSONObject jsonObject1 = jsonObjectLinesNew.getJSONObject(0);
                JSONObject jsonObject2 = jsonObjectLinesNew.getJSONObject(jsonObjectLinesNew.size() - 1);
                topLine = jsonObject1.getDouble("top");
                leftLine = jsonObject1.getDouble("left");
                Double leftLT2 = jsonObject2.getDouble("left");
                Double widthLine2 = jsonObject2.getDouble("width");
                widthLine = leftLT2 - leftLine + widthLine2;
                heightLine = jsonObject1.getDouble("height");

            } else if (jsonObjectLinesNew.size() == 1) {
                JSONObject jsonObjectLine = jsonObjectLinesNew.getJSONObject(0);
                topLine = jsonObjectLine.getDouble("top");
                leftLine = jsonObjectLine.getDouble("left");
                widthLine = jsonObjectLine.getDouble("width");
                heightLine = jsonObjectLine.getDouble("height");
                textLine = jsonObjectLine.getString("text");
            } else if (jsonObjectLinesNew.size() < 1) {

                continue;
            }

            String lineId = "line_" + i + "_" + i2 + "_" + getRandomString(12);
            line.put("lineNo", i2);
            line.put("objContent", textLine);
            line.put("lineId", lineId);
            line.put("objType", "textLine");
            line.put("objPos", new double[]{topLine, leftLine, widthLine, heightLine});
            lines.add(line);

        }
    }

    public static void extractedTables(int i, JSONArray table, JSONArray lines, JSONArray textData) {
        //包含表格

        /*
         * 变量放在这里意思是拿到该页的最有一个表格？
         * */
        JSONArray dataT = null;

        LinkedList<Integer> linId = new LinkedList<>();

        for (int i2 = 0; i2 < textData.size(); i2++) {
            JSONObject line = new JSONObject();
            JSONArray jsonObjectLines = textData.getJSONArray(i2);


            JSONArray jsonObjectLinesNew = new JSONArray();
            Double topLine = null;
            Double leftLine = null;
            Double widthLine = null;
            Double heightLine = null;
            String textLine = "";

            for (int i1 = 0; i1 < jsonObjectLines.size(); i1++) {
                JSONObject jsonObjectLine1 = jsonObjectLines.getJSONObject(i1);
                Double topLineL = jsonObjectLine1.getDouble("top");
                Double leftLineL = jsonObjectLine1.getDouble("left");
                Double widthLineL = jsonObjectLine1.getDouble("width");
                Double heightLineL = jsonObjectLine1.getDouble("height");
                String textLineL = jsonObjectLine1.getString("text");

                if (!topLineL.equals(0) && !leftLineL.equals(0) && !widthLineL.equals(0) && !heightLineL.equals(0)) {
                    if (!textLineL.equals("")) {
                        jsonObjectLinesNew.add(jsonObjectLine1);
                        textLine += textLineL;
                    }
                }
            }

            if (jsonObjectLinesNew.size() > 1) {
                JSONObject jsonObject1 = jsonObjectLinesNew.getJSONObject(0);
                JSONObject jsonObject2 = jsonObjectLinesNew.getJSONObject(jsonObjectLinesNew.size() - 1);
                topLine = jsonObject1.getDouble("top");
                leftLine = jsonObject1.getDouble("left");
                Double leftLT2 = jsonObject2.getDouble("left");
                Double widthLine2 = jsonObject2.getDouble("width");
                widthLine = leftLT2 - leftLine + widthLine2;
                heightLine = jsonObject1.getDouble("height");

            } else if (jsonObjectLinesNew.size() == 1) {
                JSONObject jsonObjectLine = jsonObjectLinesNew.getJSONObject(0);
                topLine = jsonObjectLine.getDouble("top");
                leftLine = jsonObjectLine.getDouble("left");
                widthLine = jsonObjectLine.getDouble("width");
                heightLine = jsonObjectLine.getDouble("height");
                textLine = jsonObjectLine.getString("text");
            } else if (jsonObjectLinesNew.size() < 1) {

                continue;
            }


            //处理表格
            for (int i3 = 0; i3 < table.size(); i3++) {
                JSONObject jsonObjectT = table.getJSONObject(i3);

                String extraction_method = jsonObjectT.getString("extraction_method");
                Double lefT = jsonObjectT.getDouble("left");
                Double topT = jsonObjectT.getDouble("top");
                Double widthT = jsonObjectT.getDouble("width");
                Double heightT = jsonObjectT.getDouble("height");
                Double rightT = jsonObjectT.getDouble("right");
                Double bottomT = jsonObjectT.getDouble("bottom");
                dataT = jsonObjectT.getJSONArray("data");


                if (topT < topLine && bottomT > (topLine + heightLine)) {
                    linId.add(i2);

                } else {
                    String lineId = "line_" + i + "_" + i2 + "_" + getRandomString(12);
                    line.put("lineNo", i2);
                    line.put("objContent", textLine);
                    line.put("lineId", lineId);
                    line.put("objType", "textLine");
                    line.put("objPos", new double[]{topLine, leftLine, widthLine, heightLine});
                    if (!lines.contains(line)) {
                        lines.add(line);
                    }

                }
            }

        }
        Integer table_Line = linId.get(0);

        for (int i4 = 0; i4 < dataT.size(); i4++) {
            JSONObject lineT = new JSONObject();
            JSONArray jsonArrayTableLines = dataT.getJSONArray(i4);

            JSONArray jsonArrayLin = new JSONArray();
            for (int i5 = 0; i5 < jsonArrayTableLines.size(); i5++) {
                JSONObject lin = new JSONObject();
                JSONObject jsonArrayTableLine = jsonArrayTableLines.getJSONObject(i5);
                String text = jsonArrayTableLine.getString("text");
                if (!text.equals("")) {
                    lin.put("objContent", text);
                    lin.put("objPos", new double[]{jsonArrayTableLine.getDouble("top"), jsonArrayTableLine.getDouble("left"), jsonArrayTableLine.getDouble("width"), jsonArrayTableLine.getDouble("height")});
                    jsonArrayLin.add(lin);
                }
            }

            if (jsonArrayLin.size() > 0) {
                String lineIdT = "line_" + i + "_" + (table_Line) + "_" + getRandomString(12);
                lineT.put("lineNo", table_Line);
                lineT.put("objContent", jsonArrayLin);
                lineT.put("lineId", lineIdT);
                lineT.put("objType", "table");
                lineT.put("objPos", new double[]{0, 0, 0, 0});
                lines.add(lineT);
                table_Line++;
            }
        }


    }

    //随机生成字符串
    public static String getRandomString(int length) {
        String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(62);
            sb.append(str.charAt(number));
        }
        return sb.toString();
    }

    public static List<String> sortList(List<String> texts) {
        LinkedList linkedList = new LinkedList();
        Map<Integer, String> map = new HashMap<>();
        for (int i = 0; i < texts.size(); i++) {
            String filename = texts.get(i);
            Integer page = Integer.valueOf(filename.substring(filename.lastIndexOf("_") + 1, filename.lastIndexOf(".")));
            map.put(page, filename);
        }
        for (int i = 0; i < map.size(); i++) {
            String filenamePath = map.get(i);
            linkedList.add(filenamePath);
        }
        return linkedList;
    }


}
